﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System.Runtime.Remoting;
using System.Windows;
using University.Workshop.DataAccess;
using System.Collections.ObjectModel;
using System.Windows.Controls;
namespace University.Workshop.Model
{
    public class PokerServer
    {
        private Collection<Thread> clientThreadsArray = new Collection<Thread>();
        private Collection<NetworkStream> comunicationChannel = new Collection<NetworkStream>();
        private Collection<NetworkStream> Channel = new Collection<NetworkStream>();
        public TcpListener TcpListener{get;set;}
        private Thread listenThread;
        private volatile bool serverIsIdle = false;
        private Collection<ClientManager> clientManager = new Collection<ClientManager>();
       public int Number {get;set;}
        public int Port { get; set; }
        Thread clientThread;
        public string Parameter { get; set; }
        ClientManager newClientAttended;
        bool[] status = new bool[5];
        private TextBox text;
        public PokerServer()
        {
            text = new TextBox();
            listenThread = new Thread(ListenForClients);
            Number = -1;
        }
        public PokerServer(TextBox newText)
        {
            text = newText;
            listenThread = new Thread(ListenForClients);
            Number = -1;
           
        }
        public void ShutdownServer()
        {
            serverIsIdle = true;
        }

        public void InitializeServer(object port)
        {
            try
            {
                this.Port = (int)port;
                TcpListener = new TcpListener(IPAddress.Any, this.Port);
                GlobalString.Instance.Message = Resources.message2;
                listenThread = new Thread(ListenForClients);
                listenThread.Start();
            }
            catch (ArgumentNullException nullException)
            {
                //Stop Listen's Thread && disable server services
                DisconnectClients();
                ShutdownServer();
                listenThread.Join();
                GlobalString.Instance.Message = Resources.message3+nullException;
            }
            catch (ArgumentOutOfRangeException outOfRange)
            {
                //Stop Listen's Thread
                DisconnectClients();
                ShutdownServer();
                listenThread.Join();
               
                GlobalString.Instance.Message =Resources.message3 + outOfRange;
            }

        }
        
        public void ListenForClients()
        {
            text.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(delegate()
            {
                this.Parameter=DateTime.Now + " the Server was Started";
                    text.Text =this.Parameter ;
                    this.Parameter = " ";
                    text.Text = this.Parameter; ;
            }));

            try
            {

                TcpListener.Start();

            }
            catch (SocketException error)
            {
                TcpListener.Stop();
                DisconnectClients();
                ShutdownServer();
                listenThread.Join();
                GlobalString.Instance.Message = Resources.message5 +error.Message;
            }
            
            while (!serverIsIdle)
            {


                try
                {
                    TcpClient client = TcpListener.AcceptTcpClient();
                    GlobalString.Instance.Message = Resources.message4;
                    newClientAttended = new ClientManager(client,Port,text);
        //            newClientAttended.send("Start");
          //          string conecttion = newClientAttended.receive();
            //        newClientAttended.send("Accepted"); 
                    if (Port<3000)
                    {
                        clientThread = new Thread(new ParameterizedThreadStart(AttendTable));
                        clientThread.Start(newClientAttended);
                        clientThreadsArray.Add(clientThread);
                    
                    
                    }
                    else
                    {
                        clientThread = new Thread(newClientAttended.SendReceiveAnswer);
                        clientThread.Start();
                        clientThreadsArray.Add(clientThread);
                    }
                }
                catch (InvalidOperationException e)
                {
                    GlobalString.Instance.Message = Resources.message1 +e.Message;
                }
                catch (SocketException e)
                {
                    GlobalString.Instance.Message = Resources.message1 + e.Message;
                }
                
            }
        }
        private void AttendTable(object manager)
        {

            
            ClientManager ClientAttended = (ClientManager)manager;
            int StatusIndex=ClientAttended.MyId;
            status[StatusIndex] = true;
            
            bool next;
            do
            {
                next=true;
                for (int iterator = 0; iterator < ClientAttended.MyId;iterator++ )
                {
                    if (status[iterator]) next = false;
                }
            }while(!next);
            string[] data = ClientAttended.Receive().Split(' ');
            this.Parameter = "ok";
            ClientAttended.Send(Parameter);
            if (data[0] == "00")
            {
                
                 ClientAttended.SendReceiveAnswer();
                 if (!ClientAttended.Delete)
                 {
                     
                     ClientAttended.SendToAllUsers(TableManager.Instance.Tables[Port - 2999].Partners);
                     comunicationChannel.Add(ClientAttended.ClientStream);
                 
                 }
                  
                 
            }
            else 
            {
                if (data[0] == "01")
                { 
                    TableManager.Instance.Tables[0].CardStream.Add(ClientAttended.ClientStream);
                } //newClientAttended.partners = comunicationChannel;
                else
                {
                    clientThread = new Thread(newClientAttended.SendReceiveAnswer);
                    clientThread.Start();
                    clientThreadsArray.Add(clientThread);
                }
            }
            status[StatusIndex] = false;
            
        }
        public void DisconnectServer()
        {
            foreach (Thread client in clientThreadsArray)
            {
                if (client.IsAlive)
                {
                    client.IsBackground = true;
                    client.Abort();
                }
            }
            if (listenThread.IsAlive)
            {
                listenThread.IsBackground = true;
                listenThread.Abort();
            }
            if(TcpListener!=null)    
            TcpListener.Stop();
        }
        
        public void DisconnectClients()
        {
            foreach (NetworkStream TheClient in comunicationChannel)
                TheClient.Close();
            foreach (NetworkStream TheClient in Channel)
                TheClient.Close();

            foreach (ClientManager EachOneOfClients in clientManager)
            {
                EachOneOfClients.DisconnectClient();
            }
        }


    }
}
